﻿using System.Collections.Generic;
using LFloatMath.Collision2D;
using LFloatMath.Math;

namespace IQIGame.Onigao.Logic
{
    public class CollisionUtil
    {
        private static Dictionary<ECollisionType, Dictionary<long, ColliderPrefab>> prefabCache = new Dictionary<ECollisionType, Dictionary<long, ColliderPrefab>>();

        public static ColliderPrefab GetCirclePrefab(LFloat rRadius)
        {
            return GetPrefab(ECollisionType.Circle, rRadius, default, default, default);
        }
        
        public static ColliderPrefab GetCubePrefab(LFloat rWidth, LFloat rHeight, LVector2 rUp)
        {
            return GetPrefab(ECollisionType.Cube, rWidth, rHeight, rUp.x, rUp.y);
        }

        public static ColliderPrefab GetFanPrefab(LFloat rRadius, LFloat rAngle, LVector2 rForward)
        {
            return GetPrefab(ECollisionType.Fan, rRadius, rAngle, rForward.x, rForward.y);
        }

        private static ColliderPrefab GetPrefab(ECollisionType rType, LFloat rParam1, LFloat rParam2, LFloat rParam3, LFloat rParam4)
        {
            long nHash = rParam1._val | rParam2._val << 16| rParam3._val << 32;
            if (prefabCache.TryGetValue(rType, out var rCache))
            {
                if (rCache.TryGetValue(nHash, out var prefab))
                {
                    return prefab;
                }
            }
            else
            {
                rCache = new Dictionary<long, ColliderPrefab>();
                prefabCache.Add(rType, rCache);
            }

            var rPrefab = CreatePrefab(rType, rParam1, rParam2, rParam3, rParam4);
            prefabCache[rType][nHash] = rPrefab;
            return rPrefab;
        }

        private static ColliderPrefab CreatePrefab(ECollisionType rType, LFloat rParam1, LFloat rParam2, LFloat rParam3, LFloat rParam4)
        {
            var prefab = new ColliderPrefab();
            switch (rType)
            {
                case ECollisionType.Circle:
                    prefab.parts.Add(new ColliderPart()
                    {
                        transform = new CTransform2D(LVector2.zero),
                        collider = new CCircle(rParam1)
                    });
                    break;
                case ECollisionType.Cube:
                    prefab.parts.Add(new ColliderPart()
                    {
                        transform = new CTransform2D(LVector2.zero),
                        collider = new COBB(new LVector2(rParam1, rParam2), new LVector2(rParam3, rParam4))
                    });
                    break;
                case ECollisionType.Fan:
                    prefab.parts.Add(new ColliderPart()
                    {
                        transform = new CTransform2D(LVector2.zero),
                        collider = new CFan(rParam1, rParam2, new LVector2(rParam3, rParam4))
                    });
                    break;
            }

            return prefab;
        }
    }

    public enum ECollisionType
    {
        None,
        Circle,
        Cube,
        Fan
    }
}